package edu.ustb.mis.dm.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * 聚类结果的类别实例
 * 
 * @author Saya
 */
public class ClusterResult implements Serializable, Comparable<ClusterResult> {
	private static final long serialVersionUID = 2588250205895331757L;

	/**
	 * 用来存储类中实例的名称（标识）
	 */
	private List<String> classIDList = new ArrayList<String>();

	private final Map<String, Integer> idMap = new HashMap<String, Integer>();

	/**
	 * 类中实例属性的集合
	 */
	private BitSet sameSet = new BitSet();

	/**
	 * 类中实例属性的全集
	 */
	private BitSet allSet = new BitSet();

	/**
	 * 差异度
	 */
	private float dissimilarity = 0f;

	public ClusterResult() {
	}

	/**
	 * 构造函数,给定类标识和初始属性集
	 */
	public ClusterResult(final String classID, final BitSet initSet) {
		this.classIDList.add(classID);
		this.sameSet.or(initSet);
		this.allSet.or(initSet);
	}

	public void add(final List<String> classIDList, final ClusterResult cr, final float dissimilarity) {
		this.classIDList.addAll(classIDList);
		this.same(cr.getSameSet());
		this.merge(cr.getAllSet());
		this.dissimilarity = dissimilarity;
	}

	/**
	 * 添加新的元素入类 1、添加类标示 2、比对属性 3、修改差异度
	 * 
	 * @param classID
	 * @param attributes
	 * @param dissimilarity
	 */
	public void add(final String classID, final BitSet attributes, final float dissimilarity) {
		this.classIDList.add(classID);
		this.same(attributes);
		this.merge(attributes);
		this.dissimilarity = dissimilarity;
	}

	/**
	 * 添加新的类标识
	 * 
	 * @param classID
	 */
	public void addClass(final String classID) {
		this.classIDList.add(classID);
	}

	/**
	 * 返回所有集合的属性数目
	 * 
	 * @return
	 */
	public int allSize() {
		return this.allSet.cardinality();
	}

	/**
	 * 清空一个实例，包括类标识
	 */
	public void clear() {
		this.classIDList.clear();
		this.clearSet();
	}

	/**
	 * 清空一个实例，只是属性集
	 */
	public void clearSet() {
		this.sameSet.clear();
		this.allSet.clear();
	}

	public int compareTo(final ClusterResult o) {
		return Double.compare(o.effectiveSize(), this.effectiveSize());
	}

	/**
	 * 与给定集合进行比对，得出相同的属性集合不同的属性集
	 * 
	 * @param set
	 */
	public void contrast(final BitSet set) {
		this.same(set);
		this.merge(set);
	}

	public void contrast(final ClusterResult cr) {
		this.same(cr.getSameSet());
		this.merge(cr.getAllSet());
	}

	/**
	 * 返回不同属性的数目
	 * 
	 * @return
	 */
	public float diffSize() {
		return this.allSize() - this.sameSize();
	}

	public int effectiveSize() {
		final List<KVPair> kvList = new ArrayList<KVPair>();
		for (String id : classIDList) {
			id = id.substring(id.length() - 1);
			if (idMap.containsKey(id)) {
				idMap.put(id, idMap.get(id) + 1);
			} else {
				idMap.put(id, 1);
			}
		}
		if (idMap.keySet().size() == 1) {
			return this.getClassIDList().size();
		} else {
			for (final Entry<String, Integer> entry : idMap.entrySet()) {
				kvList.add(new KVPair(entry));
			}
			Collections.sort(kvList);
			return kvList.get(0).getValue();
		}
	}

	public BitSet getAllSet() {
		return allSet;
	}

	public List<String> getClassIDList() {
		return classIDList;
	}

	public float getDissimilarity() {
		return dissimilarity;
	}

	public BitSet getSameSet() {
		return sameSet;
	}

	/**
	 * 数据初始化，给定属性及，没有类标识，用于tmp存储
	 * 
	 * @param initSet
	 * @return
	 */
	public ClusterResult init(final BitSet initSet) {
		this.sameSet.or(initSet);
		this.allSet.or(initSet);
		return this;
	}

	/**
	 * 初始化方法，没有类标识，给定sameSet和allSet,用于tmp存储
	 * 
	 * @param sameSet
	 * @param allSet
	 * @return
	 */
	public ClusterResult init(final BitSet sameSet, final BitSet allSet) {
		this.sameSet.or(sameSet);
		this.allSet.or(allSet);
		return this;
	}

	/**
	 * 数据初始化,给定类标识和一个初始属性集，将sameSet和allSet置为同一值
	 * 
	 * @param classID
	 * @param initSet
	 * @return
	 */
	public ClusterResult init(final String classID, final BitSet initSet) {
		this.classIDList.add(classID);
		this.sameSet.or(initSet);
		this.allSet.or(initSet);
		return this;
	}

	/**
	 * 计算全集
	 * 
	 * @param bitSet
	 */
	public void merge(final BitSet bitSet) {
		this.allSet.or(bitSet);
	}

	/**
	 * 如添加新元素的话类内将达到属性数量
	 * 
	 * @return
	 */
	public int nextSize() {
		return size() + 1;
	}

	public int nextSize(final ClusterResult cr) {
		return size() + cr.size();
	}

	/**
	 * 删除类标识
	 * 
	 * @param classID
	 * @return
	 */
	public boolean removeClass(final String classID) {
		return this.classIDList.remove(classID);
	}

	/**
	 * 计算相同属性
	 * 
	 * @param bitSet
	 */
	public void same(final BitSet bitSet) {
		this.sameSet.and(bitSet);
	}

	/**
	 * 返回相同属性集合的属性数目
	 * 
	 * @return
	 */
	public int sameSize() {
		return this.sameSet.cardinality();
	}

	public void setAllSet(final BitSet allSet) {
		this.allSet = allSet;
	}

	public void setClassIDList(final List<String> classIDList) {
		this.classIDList = classIDList;
	}

	public void setDissimilarity(final float dissimilarity) {
		this.dissimilarity = dissimilarity;
	}

	public void setSameSet(final BitSet sameSet) {
		this.sameSet = sameSet;
	}

	/**
	 * 类内元素数量
	 * 
	 * @return
	 */
	public int size() {
		return this.classIDList.size();
	}
}
